from zipfile import PyZipFile, ZIP_DEFLATED
from datetime import date
from khronos.utils import Logger, Prompt
from khronos.utils.files import find_files, suffix_filter, file_size
import os

_log = Logger()
_prompt = Prompt("Continue anyway?")

def zip_package(pkg_dir, major="X", minor="X", build="X", release_type="", 
                include_filters=(), verbose=True):
    """Make a zip archive of python source files contained in 'pkg_dir'. The filename of the 
    zip archive is
        [pkg_name]_[major].[minor].[build][release_type]_[date].zip
    and it is placed inside the designated package's directory. Actually, the 'pkg_dir' argument 
    may be any directory containing source code, even if it is not a package. The 'pkg_name' part 
    of the archive's filename is obtained from the last part of the specified directory's path, 
    using os.split()."""
    _log.set_enabled(verbose)
    pkg_dir = os.path.abspath(pkg_dir)
    pkg_loc, pkg_name = os.path.split(pkg_dir)
    today = date.today()
    fname = "%s_%s.%s.%s%s_%d%02d%02d.zip" % (pkg_name, major, minor, build, release_type, 
                                              today.year, today.month, today.day)
    fpath = os.path.join(pkg_dir, fname)
    _log.info("Creating zip file %s at %s" % (fname, pkg_dir))
    if os.path.exists(fpath):
        _log.warn("Archive %s already exists. Continuing will overwrite the old file." % (fpath,))
        answer = _prompt()
        if answer not in ("y", "yes"):
            return
            
    filters = [suffix_filter(".py"), suffix_filter(".pyx")]
    filters.extend(include_filters)
    archive = PyZipFile(fpath, "w", ZIP_DEFLATED)
    filematches = find_files(pkg_dir, filters, recursive=True)
    for filepath in filematches:
        _log(filepath, indent=1)
        zippath = filepath[len(pkg_loc):]
        archive.write(filepath, zippath)
    archive.close()
    _log.info("%d files added to archive (%s). Zip file %s created successfully at %s" %
              (len(filematches), file_size(fpath), fname, pkg_dir))
              
if __name__ == "__main__":
    from optparse import OptionParser
    import sys
    
    parser = OptionParser(description="Utility for creating Python source code zip archives.", 
                          usage="%prog [options]", version="%prog 0.0.1a")
    parser.add_option("-d", "--directory", dest="directory", type="string", default=".", 
                      help="specify the target directory (default is '.')")
    parser.add_option("-M", "--major", dest="major", type="int", default=0, 
                      help="version major number (first component of the version number)")
    parser.add_option("-m", "--minor", dest="minor", type="int", default=0, 
                      help="version minor number (second component of the version number)")
    parser.add_option("-b", "--build", dest="build", type="int", default=0, 
                      help="version build number (third component of the version number)")
    parser.add_option("-r", "--release-type", dest="rtype", type="string", default="", 
                      help="version release type (a, b, rc)")
    parser.add_option("-i", "--include", dest="include", type="str", action="append", 
                      help="specifies a suffix for filenames that will "
                      "also be added to the package")
    
    options, args = parser.parse_args(sys.argv)
    filters = [] if options.include is None else [suffix_filter(s) for s in options.include]
    zip_package(options.directory, options.major, options.minor, 
                options.build, options.rtype, filters)
    sys.exit(0)
    
